﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Collections.Specialized;
using System.Drawing.Drawing2D;

namespace QuadRemote.Panels
{
    public struct QuadPanelSettings
    {
        public int x;
        public int y;
        public int width;
        public int height;
        public bool minimized;
    }

    public abstract class QuadPanel : Panel
    {
        private const int MARGIN_X = 2;
        private const int MARGIN_Y = 28;

        protected Label resize;
        protected Label title;
        protected Label _closeButton;
        protected Label _minimizeButton;
        protected int _normalHeight;
        protected bool _resizable;
        protected bool _paintable;

        private Timer repaintTimer;
        protected DrawingPanel drawingPanel;
        protected int margin = 7;
        protected int border = 2;
        protected int _minWidth = 60;
        protected int _minHeight = 0;
        protected int _maxWidth = 1600;
        protected int _maxHeight = 1600;
        protected bool lockAspect = false;
        protected string _name;
        public Color panelColor;
        protected bool _minimized;

        protected QuadPanelSettings getSettings(int defaultWidth, int defaultHeight)
        {
            StringCollection collection = Properties.Settings.Default.Panels;
            QuadPanelSettings settings = new QuadPanelSettings();
            
            if (collection != null)
            {
                foreach (string s in collection)
                {
                    string[] split = s.Split(';');
                    if (split[0] == _name)
                    {
                        settings.x = int.Parse(split[1]);
                        settings.y = int.Parse(split[2]);
                        settings.width = int.Parse(split[3]);
                        settings.height = int.Parse(split[4]);
                        settings.minimized = split.Length > 5 && split[5] == "1";
                        return settings;
                    }
                }
            }

            settings.x = MARGIN_X;
            settings.y = MARGIN_Y;
            settings.width = defaultWidth;
            settings.height = defaultHeight;
            settings.minimized = false;
            return settings;
        }


        
        protected override void OnPaintBackground(System.Windows.Forms.PaintEventArgs e)
        {
            Rectangle rc = new Rectangle(0, 0, this.ClientSize.Width, this.ClientSize.Height);
            //LinearGradientBrush brush = new LinearGradientBrush(rc, Color.FromArgb(160, panelColor), Color.FromArgb(80, panelColor), 45F);
            SolidBrush brush = new SolidBrush(this.BackColor);
            GraphicsPath p = new GraphicsPath();
            p.AddLine(Width - border, 0, Width, border);
            p.AddLine(Width, Height - border, Width - border, Height);
            p.AddLine(border , Height, 0, Height - border);
            p.AddLine(0, border, border , 0);

            e.Graphics.FillPath(brush, p);
        }

        protected void saveSettings()
        {
            StringCollection collection = Properties.Settings.Default.Panels;
            StringCollection newCollection = new StringCollection();

            bool found = false;
            string newS = _name + ";" + Left + ";" + Top + ";" + Width + ";" + _normalHeight + ";" + (_minimized ? "1" : "0");

            if (collection != null)
            {
                foreach (string s in collection)
                {
                    string[] split = s.Split(';');
                    if (split[0] == _name)
                    {
                        newCollection.Add(newS);
                        found = true;
                    }
                    else
                    {
                        newCollection.Add(s);
                    }
                }
            }
            
            if (!found)
                newCollection.Add(newS);
            Properties.Settings.Default.Panels = newCollection;
            Properties.Settings.Default.Save();
        }

        public QuadPanel(string name, int defaultWidth, int defaultHeight, Color panelC, int refreshRate)
        {
            _name = name;
            panelColor = panelC;

            DoubleBuffered = true;

            /*
            defaultWidth += margin * 2 + border*2;
            defaultHeight += margin * 2 + border*2;
            defaultHeight += 20;*/

            defaultWidth -= 2;
            defaultHeight -= 2;
            BorderStyle = BorderStyle.None;

            title = new Label();
            title.Text = name;
            title.Font = new System.Drawing.Font("Helvetica", 7, System.Drawing.FontStyle.Regular);
            title.Padding = new Padding(2,2,2,0);
            title.Left = border;
            title.Top = border;
            title.Height = 20;
            title.MouseDown += new System.Windows.Forms.MouseEventHandler(Mouse);
            title.MouseUp += new System.Windows.Forms.MouseEventHandler(Mouse);
            title.MouseMove += new System.Windows.Forms.MouseEventHandler(Mouse);
            title.Cursor = Cursors.SizeAll;
            title.Name = "Title";
            Controls.Add(title);

            _closeButton = new Label();
            _closeButton.Text = "X";
            _closeButton.Font = new System.Drawing.Font("Helvetica", 7, System.Drawing.FontStyle.Regular);
            _closeButton.Padding = new Padding(2, 2, 2, 0);
            _closeButton.Cursor = Cursors.Hand;
            _closeButton.Height = 20;
            _closeButton.MouseClick += new MouseEventHandler(ClosePanel);
            Controls.Add(_closeButton);

            _minimizeButton = new Label();
            _minimizeButton.Text = "_";
            _minimizeButton.Font = new System.Drawing.Font("Helvetica", 7, System.Drawing.FontStyle.Regular);
            _minimizeButton.Padding = new Padding(2, 2, 2, 0);
            _minimizeButton.Cursor = Cursors.Hand;
            _minimizeButton.Height = 20;
            _minimizeButton.MouseClick += new MouseEventHandler(ToggleMinimize);
            Controls.Add(_minimizeButton);

            resize = new Label();
            resize.Text = "";
            resize.Width = 8;
            resize.Height = 8;
            resize.Cursor = Cursors.PanSE;
            resize.BackColor = System.Drawing.Color.White;
            resize.MouseDown += new System.Windows.Forms.MouseEventHandler(Mouse);
            resize.MouseUp += new System.Windows.Forms.MouseEventHandler(Mouse);
            resize.MouseMove += new System.Windows.Forms.MouseEventHandler(Mouse);
            resize.Name = "Resize";
            Controls.Add(resize);

            _resizable = true;
            _paintable = true;

            drawingPanel = new DrawingPanel();
            drawingPanel.Paint += new System.Windows.Forms.PaintEventHandler(Draw);
            Controls.Add(drawingPanel);


            if (refreshRate > 0)
            {
                repaintTimer = new Timer();
                repaintTimer.Enabled = true;
                repaintTimer.Interval = refreshRate;
                repaintTimer.Tick += new EventHandler(this.repaintTick);
            }
            else
                _paintable = false;

            QuadPanelSettings settings = getSettings(defaultWidth, defaultHeight);
            Width = settings.width;
            Height = _normalHeight = settings.height;
            
            Left = settings.x;
            Top = settings.y;
            if (settings.minimized) ToggleMinimize(this, null);

            reposition();
        }

        private void ClosePanel(object sender, EventArgs args)
        {
            //((MainWindow)Parent).togglePanel(this);
        }

        private void ToggleMinimize(object sender, EventArgs args)
        {
            _minimized = !_minimized;
            if (_minimized)
            {
                _normalHeight = Height;
                Height = 20 + border;
                if (_paintable) repaintTimer.Enabled = false;
                resize.Hide();
            }
            else
            {
                Height = _normalHeight;
                if (_paintable) repaintTimer.Enabled = true;
                if (_resizable) resize.Show();
            }

            saveSettings();
            reposition();
            Invalidate();
        }

        public virtual void resized()
        {

        }

        private int mouseX = -1;
        private int mouseY = -1;

        protected void reposition()
        {
            BackColor = panelColor;
            
            //title.ForeColor = Color.FromArgb(255, (int)(panelColor.R * 0.2), (int)(panelColor.G * 0.2), (int)(panelColor.B * 0.2));
            title.ForeColor = Color.Black;
            //drawingPanel.BackColor = Color.Transparent;
            //drawingPanel.BackColor = Color.FromArgb(255, (int)(panelColor.R * 0.1), (int)(panelColor.G * 0.1), (int)(panelColor.B * 0.1));
            drawingPanel.BackColor = Color.FromArgb(255,panelColor.R/5,panelColor.G/5,panelColor.B/5);
            resize.BackColor = panelColor;
            title.Width = Width-border*2-32;

            _minimizeButton.Width = 16;
            _minimizeButton.Left = title.Left + title.Width;
            _minimizeButton.Top = border;
            _minimizeButton.ForeColor = Color.FromArgb(255, (int)(panelColor.R * 0.2), (int)(panelColor.G * 0.2), (int)(panelColor.B * 0.2));
            //_minimizeButton.BackColor = panelColor;

            _closeButton.Width = 16;
            _closeButton.Left = _minimizeButton.Left + _minimizeButton.Width;
            _closeButton.Top = border;
            _closeButton.ForeColor = Color.FromArgb(255, (int)(panelColor.R * 0.2), (int)(panelColor.G * 0.2), (int)(panelColor.B * 0.2));
            //_closeButton.BackColor = panelColor;
            
            drawingPanel.Top = title.Top + title.Height;
            drawingPanel.Left = border;
            drawingPanel.Width = Width-border*2;
            drawingPanel.Height = Height - drawingPanel.Top-border;

            resize.Left = Width - resize.Width;
            resize.Top = Height - resize.Height;

            resized();
        }

        public int PanelHeight
        {
            get { return drawingPanel.Height - 2 * margin; }
        }

        public int PanelWidth
        {
            get { return drawingPanel.Width - 2 * margin; }
        }

        public void Mouse(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            Label l = (Label)sender;

            if (l.Name == "Title")
            {
                if (e.Button == MouseButtons.Left)
                {
                    if (mouseX == -1)
                    {
                        mouseX = e.X;
                        mouseY = e.Y;
                        BringToFront();
                    }
                    else
                    {
                        int mTop = (int)Math.Round((double)(Top + (e.Y - mouseY)) / 20) * 20 + (MARGIN_Y-20);
                        if (mTop < MARGIN_Y) mTop = MARGIN_Y;
                        int mLeft = (int)Math.Round((double)(Left + (e.X - mouseX)) / 20) * 20 + MARGIN_X;
                        if (mLeft < MARGIN_X) mLeft = MARGIN_X;
                        Top = mTop;
                        Left = mLeft;
                    }
                }
                else
                {
                    mouseX = mouseY = -1;
                    saveSettings();
                }
            }
            else if (l.Name == "Resize")
            {
                if (e.Button == MouseButtons.Left)
                {
                    if (mouseX == -1)
                    {
                        mouseX = e.X;
                        mouseY = e.Y;
                    }
                    else
                    {
                        int newHeight = (int)Math.Round((double)(Height + (e.Y - mouseY)) / 20) * 20-2;
                        int newWidth = (int)Math.Round((double)(Width + (e.X - mouseX)) / 20) * 20-2;

                        if (newHeight < _minHeight) newHeight = _minHeight-2;
                        if (newWidth < _minWidth) newWidth = _minWidth-2;
                        if (newHeight > _maxHeight) newHeight = _maxHeight-2;
                        if (newWidth > _maxWidth) newWidth = _maxWidth-2;

                        if (lockAspect)
                        {
                            if (newHeight != Height || newWidth != Width)
                            {
                                if (newHeight != Height) { mouseX -= (newHeight - Height); newWidth = newHeight - 20; }
                                else if (newWidth != Width) { mouseY -= (newWidth - Width); newHeight = newWidth + 20; }
                            }
                        }

                        bool shouldSave = false;
                        if (_normalHeight != newHeight ||
                            newWidth != Width)
                            shouldSave = true;

                        _normalHeight = newHeight;
                        
                        if (!_minimized)
                            Height = newHeight;
                        
                        Width = newWidth;

                        reposition();
                        if (shouldSave) saveSettings();
                    }
                }
                else
                {
                    mouseX = mouseY = -1;
                    saveSettings();
                }
            }
        }

        public void repaintTick(object sender, EventArgs e)
        {
            //if (_name == "Log") Parent.Invalidate();
            //Invalidate();
            //Invalidate(this.ClientRectangle,true);
            drawingPanel.Invalidate();
            //drawingPanel.Invalidate(
        }

        public virtual void Draw(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            System.Drawing.Drawing2D.Matrix m = new System.Drawing.Drawing2D.Matrix(1, 0, 0, 1, margin, margin);
            g.Transform = m;
            PaintPanel(g);
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
        }


        public abstract void PaintPanel(Graphics g);

        public virtual void removed()
        {
            if (repaintTimer != null)
                repaintTimer.Enabled = false;
            saveSettings();
        }
    }
}
